package homework_3_by_ly;

import java.util.ArrayList;

/**
 * 
 * @author by Liuyang
 * 
 *
 */

public class Figure_Extract {

	// DO NOT write FFT.WINDOW_SIZE / 44100, it equals to 0 forever!!
    public static final double scaling = FFT.WINDOW_SIZE / 44100.0;
    public final static int[] RANGE = new int[]{110,220,440,880,1760};
    public static final int N = 4;

    private ArrayList<int[]> constel_data = new ArrayList<>();
    private int id;

    /**
     * For songs about to add into DB
     * @param id
     */
    public Figure_Extract(int id) {
        this.id = id;
    }

    /**
     * For songs about to be searched
     */
    public Figure_Extract() {
        this.id = -1;
    }

    /**
     * Append a column of frequency peaks to the constellation map.
     * A frequency peak is a frequency value whose amplitude is the highest among
     * all frequencies in a frequency interval.
     *
     * @param freqDomain The frequency domain generated by FFT.
     */
    public void append(double[] freqDomain) 
    {
        int[] freqPeaks = new int[N];
        double[] freqMax = new double[4];
        for(int i=0;i<4;++i)
        {
            freqMax[i]=0;
        }
        for(int i=0;i<freqDomain.length;++i)
        {
        	int index = getIndex((int)(i*44100.0/4096));
        	if(index<1||index>4)
        	{
        		continue;
        	}
        	if(freqDomain[i]>freqMax[index-1])
        	{
        		freqMax[index-1]=freqDomain[i];
                freqPeaks[index-1]=(int)(i*44100.0/4096);
        	}
        }
        constel_data.add(freqPeaks);
    }
    
    /**
     * 
     * @param fre frequency
     * @return return the index of frequency
     */
    public static int getIndex(int fre)
    {
    	int i=0;
    	while(RANGE[i]<fre)
    	{
    		++i;
            if(i == 5)
                break;
    	}
    	return i;
    }

    /**
     * Generate fingerprints using Combinational Hash.
     * For each frequency peak, generate 6 fingerprints with its 6 successors.
     *  
     *
     * @return
     */
    public ArrayList<ShazamHash> combineHash() {
        if (constel_data.size() < 3)
            throw new RuntimeException("Too few frequency peaks");
        ArrayList<ShazamHash> hashes = new ArrayList<>();
        for (int i = 0; i < constel_data.size() - 2; ++i) {
            for (int k = 0; k < 4; ++k) {

            	// "Combine" with all peak frequencies inside its next two frames.
                for (int j = 1; j <= 2; ++j) {
                    for (int kk = 1; kk < 4; ++kk) {
                        ShazamHash hash = new ShazamHash();
                        hash.setf1((short) constel_data.get(i)[k]); 
                        hash.setf2((short) constel_data.get(i + j)[kk]);
                        hash.setdt((short) j); 
                        hash.setOffset(i);
                        hash.setId(id);
                        hashes.add(hash);
                    }
                }
            }
        }
        return hashes;
    }
}